package com.quan.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.quan.commons.core.bean.R;
import com.quan.commons.core.biz.support.MyBaseServiceImpl;
import com.quan.commons.core.configuration.LoginUserInterceptor;
import com.quan.commons.core.exception.BizException;
import com.quan.commons.core.utils.OrderUtils;
import com.quan.commons.core.utils.PageUtils;
import com.quan.mall.commons.vo.OmsOrderVo;
import com.quan.mall.commons.vo.OrderConfirmVo;
import com.quan.mall.commons.vo.OrderCreateTo;
import com.quan.mall.commons.vo.OrderItemVo;
import com.quan.mall.entity.*;
import com.quan.mall.mapper.OmsOrderMapper;
import com.quan.mall.service.*;
import com.quan.system.commons.vo.SysUserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class OmsOrderServiceImpl extends MyBaseServiceImpl<OmsOrderMapper, OmsOrder> implements OmsOrderService {

    @Autowired
    private OmsOrderMapper mapper;

    @Autowired
    private OmsOrderGoodsService omsOrderGoodsService;

    @Autowired
    private UmsMemberService umsMemberService;

    @Autowired
    private UmsMemberLevelService umsMemberLevelService;

    @Autowired
    private OmsOrderOperateLogService omsOrderOperateLogService;

    @Autowired
    private PmsSkuService pmsSkuService;

    @Autowired
    private PmsSpuService pmsSpuService;

    @Autowired
    private PmsBrandService pmsBrandService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private FmsFinanceCashFlowService fmsFinanceCashFlowService;

    @Autowired
    private FmsMemberCommisionFreezeService fmsMemberCommisionFreezeService;

    @Autowired
    private WmsWareSkuService wmsWareSkuService;

    @Autowired
    private WmsAgentInfoService wmsAgentInfoService;

    /**
     * 当前提交的订单信息
     */
    private ThreadLocal<OmsOrderVo> threadLocalOrderVo = new ThreadLocal<OmsOrderVo>();


    @Override
    public List<OmsOrderVo> queryList(PageUtils pageUtils, OmsOrderVo vo) {
        QueryWrapper<OmsOrder> queryWrapper = new QueryWrapper<OmsOrder>(vo);

        List<OmsOrder> list = super.list(pageUtils, queryWrapper);
        List<OmsOrderVo> collect = list.stream().map(item -> {
            OmsOrderVo bean = new OmsOrderVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public PageUtils queryPage(PageUtils pageUtils, OmsOrderVo vo) {
        QueryWrapper<OmsOrder> queryWrapper = new QueryWrapper<OmsOrder>(vo);

        if (StringUtils.isNotBlank(vo.getKeyword())) {
            queryWrapper.and(w -> {
                w.like("order_sn", vo.getKeyword())
                        .or().like("member_username", vo.getKeyword());
            });
        }

        // 查询多个状态，状态用","隔开
        if (StringUtils.isNotBlank(vo.getInStatus())) {
            queryWrapper.in("status", vo.getInStatus().split(","));
        }

        // 时间选择->0:今天;1:昨天;2:最近7天;3:最近30天:4:本月;5本年
        if (null != vo.getDateAttr()) {
            if (vo.getDateAttr() == 0) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0}", LocalDate.now());
            } else if (vo.getDateAttr() == 1) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0}", LocalDate.now().plusDays(-1));
            } else if (vo.getDateAttr() == 2) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", LocalDate.now().plusDays(-7), LocalDate.now());
            } else if (vo.getDateAttr() == 3) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", LocalDate.now().plusDays(-30), LocalDate.now());
            } else if (vo.getDateAttr() == 4) {
                // 本月的第一天
                final LocalDate firstMonthDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
                // 本月的最后一天
                final LocalDate lastMonthDay = LocalDate.now().plusYears(1).with(TemporalAdjusters.firstDayOfMonth());
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", firstMonthDay, lastMonthDay);
            } else if (vo.getDateAttr() == 5) {
                // 今年的第一天
                final LocalDate firstYearDay = LocalDate.now().with(TemporalAdjusters.firstDayOfYear());
                // 今年的最后一天
                final LocalDate lastYearDay = LocalDate.now().plusYears(1).with(TemporalAdjusters.firstDayOfYear());
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", firstYearDay, lastYearDay);
            }
        } else {
            // 下单日期范围
            if (StringUtils.isNotEmpty(vo.getDateRange())) {
                final String[] split = vo.getDateRange().split(",");
                String startDate = split[0];
                String endDate = split[1];
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", startDate, endDate);
            }
        }


        final IPage<OmsOrder> page = super.selectPage(pageUtils, queryWrapper);

        PageUtils ps = new PageUtils(page);

        final List<OmsOrder> records = page.getRecords();

        final List<OmsOrderVo> collect = records.stream().map((item) -> {
            OmsOrderVo bean = new OmsOrderVo();
            BeanUtils.copyProperties(item, bean);

            // 订单商品信息
            final List<OmsOrderGoods> orderGoods = this.omsOrderGoodsService.list(new QueryWrapper<OmsOrderGoods>().eq("order_sn", item.getOrderSn()));
            bean.setSkus(orderGoods);

            return bean;
        }).collect(Collectors.toList());

        ps.setRecords(collect);
        return ps;
    }

    @Override
    public OmsOrderVo getOrderInfo(Long id) {
        OmsOrderVo vo = new OmsOrderVo();

        final OmsOrder order = super.getById(id);
        BeanUtils.copyProperties(order, vo);

        // 订单商品信息
        final List<OmsOrderGoods> orderGoods = this.omsOrderGoodsService.list(new QueryWrapper<OmsOrderGoods>().eq("order_sn", order.getOrderSn()));
        vo.setSkus(orderGoods);

        // 会员信息
        final UmsMember member = this.umsMemberService.getById(order.getMemberId());
        vo.setMember(member);

        // 供应商
        if(null != order.getAgentId()) {
            vo.setWmsAgentInfo(this.wmsAgentInfoService.getById(order.getAgentId()));
        }


        // 订单操作日志
        final List<OmsOrderOperateLog> logs = this.omsOrderOperateLogService.list(new QueryWrapper<OmsOrderOperateLog>().eq("order_id", id));
        vo.setLogs(logs);

        return vo;
    }

    @Override
    public OmsOrder getOrderByOrderSn(String orderSn) {
        QueryWrapper<OmsOrder> queryWrapper = new QueryWrapper<OmsOrder>();
        queryWrapper.eq("order_sn", orderSn);
        return super.getOne(queryWrapper, false);
    }

    @Override
    public OrderConfirmVo confirmOrder(OrderConfirmVo vo) {
        log.info("-----------------------");
        // 构建OrderConfirmVo
        OrderConfirmVo confirmVo = new OrderConfirmVo();

        // 会员信息
        final UmsMember member = this.umsMemberService.getById(vo.getMemberId());
        // 会员级别
        final UmsMemberLevel level = this.umsMemberLevelService.getById(member.getLevelId());
        log.info("==>"+level);

        // 会员购买的商品（SKU_ID）
        List<OrderItemVo> items = vo.getItems();
        // 构建购买的订单商品
        final List<OrderItemVo> itemVos = items.stream().map(item -> {
            final PmsSku sku = this.pmsSkuService.getById(item.getSkuId());

            OrderItemVo itemVo = new OrderItemVo();
            itemVo.setSkuId(sku.getId());
            itemVo.setSkuName(sku.getSkuName());
            itemVo.setImage(sku.getSkuImg());
            itemVo.setSkuAttrValues(sku.getDescar());

            // 商品数量
            itemVo.setCount(item.getCount());
            // 查询出最新价格
            itemVo.setPrice(sku.getSalePrice());

            return itemVo;
        }).collect(Collectors.toList());

        confirmVo.setItems(itemVos);

        // 根据会员级别来设定运费
        confirmVo.setShippingType(2);


        // 商品数量
        Integer count = 0;
        if (itemVos != null && itemVos.size() > 0) {
            for (OrderItemVo item : itemVos) {
                count += item.getCount();
            }
        }
        confirmVo.setCount(count);

        // 计算实际支付价格
        BigDecimal totalAmount = BigDecimal.ZERO;
        if (itemVos != null && itemVos.size() > 0) {
            for (OrderItemVo item : itemVos) {
                //计算当前商品的总价格
                BigDecimal itemPrice = item.getPrice().multiply(new BigDecimal(item.getCount().toString()));
                //再计算全部商品的总价格
                totalAmount = totalAmount.add(itemPrice);
            }
        }
        // 打折前的金额
        confirmVo.setOriginPrice(totalAmount.setScale(2, BigDecimal.ROUND_DOWN));

        // 判断会员级别，是否满足打折条件
        if (level.getLevel() == 2 || level.getLevel() == 3 || level.getLevel() == 8) {
            log.info("=========================>>"+level.getLevel()+"===>"+level.getRebate());
            final BigDecimal ratio = new BigDecimal(level.getRebate().toString()).divide(new BigDecimal("100"));
            BigDecimal ratioAmount = totalAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
            confirmVo.setPayPrice(ratioAmount);
            log.info("==>"+confirmVo.getPayPrice());
        } else {
            confirmVo.setPayPrice(totalAmount.setScale(2, BigDecimal.ROUND_DOWN));
        }


        return confirmVo;
    }

    @Override
    public int getMemberBuyCount(Long memberId) {
        // 状态为：3->已完成，4->已关闭（手动关闭订单，退货退款成功，关闭后将不显示申请退款按钮）
        // 未申请退款
        QueryWrapper<OmsOrder> queryWrapper = new QueryWrapper<OmsOrder>();
        queryWrapper.eq("member_id", memberId);
        queryWrapper.in("status", Arrays.asList(1, 2, 3, 4));
        queryWrapper.eq("is_refund", 0);

        return super.count(queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R submitOrder(OmsOrderVo vo) {
        threadLocalOrderVo.set(vo);

        final UmsMember member = this.umsMemberService.getById(vo.getMemberId());

        vo.setMember(member);

        // 创建订单、订单项等信息
        OrderCreateTo order = createOrder(vo);

        // 验证价格，验证前端传入的价格和后台计算后的价格是否相等，前端传入的价格如：18.16，后台计算后的价格18.16839
        // 两个价格对比差值在0.01是正确的
        // 后端计算的价格
        BigDecimal payAmount = order.getOrder().getPayAmount();

        log.info("==>"+payAmount);

        // 前端传入的价格
        BigDecimal payPrice = vo.getPayAmount();
        log.info("==>"+payPrice);

        // 金额对比
        if (Math.abs(payAmount.subtract(payPrice).doubleValue()) < 0.01) {
            // 保存订单
            saveOrder(order);

            // 减库存，库存锁定,只要有异常，回滚订单数据
            Map<Long, Integer> decrSkuMap = new HashMap<>();
            // 订单商品SKU
            final List<OmsOrderGoods> orderGoods = order.getOrderGoods();
            for (OmsOrderGoods item : orderGoods) {
                //封装减库存数据
                decrSkuMap.put(item.getSkuId(), item.getSkuNum());
            }
            // 减商品sku库存
            this.pmsSkuService.decrCount(decrSkuMap);


            // 操作记录
            OmsOrderOperateLog history = new OmsOrderOperateLog();
            history.setOrderId(order.getOrder().getId());
            history.setOrderStatus(0);
            history.setOperateUser(member.getNickname());
            history.setOperateType("会员提交订单");
            history.setOperateContent("会员提交订单");
            this.omsOrderOperateLogService.save(history);

            // 订单创建之后发送消息到延时队列进行定时关单（用户下单后未付款，30分钟关闭订单）
            this.rabbitTemplate.convertAndSend("CLOSE-ORDER-EXCHANGE", "order.create", order.getOrder().getOrderSn());

            return R.ok().put("data", order.getOrder());

        } else {
            log.error("订单验证价格错误，前端传入价格：{}，后端计算后价格：{}", payPrice, payAmount);
            return R.failure("订单创建失败：验证价格错误");
        }
    }

    /**
     * 创建订单
     * @return
     */
    private OrderCreateTo createOrder(OmsOrderVo vo) {
        OrderCreateTo createTo = new OrderCreateTo();

        // 生成订单号
        String orderSn = OrderUtils.getSN();

        // 构建订单
        OmsOrder order = builderOrder(orderSn, vo);

        // 构建订单所有的商品sku
        final List<OmsOrderGoods> omsOrderGoods = builderOrderItems(orderSn);

        // 验价(计算价格、积分等信息)
        computePrice(order, omsOrderGoods);

        log.info(order.getPayAmount()+"计算价格");

        // 计算商品数量
        final int totalCount = omsOrderGoods.stream().mapToInt(item -> item.getSkuNum()).sum();
        order.setTotalCount(totalCount);

        createTo.setOrder(order);
        createTo.setOrderGoods(omsOrderGoods);

        log.info("==>"+createTo.getOrder().getPayAmount());

        return createTo;
    }


    /**
     * 构建订单
     * @param orderSn
     * @return
     */
    private OmsOrder builderOrder(String orderSn, OmsOrderVo vo) {
        final OmsOrderVo omsOrderVo = threadLocalOrderVo.get();

        // 订单信息
        OmsOrder order = new OmsOrder();
        BeanUtils.copyProperties(omsOrderVo, order);

        order.setOrderSn(orderSn);
        order.setMemberId(omsOrderVo.getMember().getId());
        order.setMemberUsername(omsOrderVo.getMember().getNickname());
        order.setMemberPhone(omsOrderVo.getMember().getMobile());
        order.setNote(vo.getNote());
        order.setExtraJson(vo.getExtraJson());
        order.setFreightAmount(vo.getFreightAmount());
        order.setCouponAmount(BigDecimal.ZERO);
        order.setDiscountAmount(BigDecimal.ZERO);

        return order;
    }

    /**
     * 构建所有订单项数据
     * @param orderSn
     * @return
     */
    private List<OmsOrderGoods> builderOrderItems(String orderSn) {
        List<OmsOrderGoods> omsOrderGoods = new ArrayList<OmsOrderGoods>();

        final OmsOrderVo omsOrderVo = threadLocalOrderVo.get();

        if (null != omsOrderVo && null != omsOrderVo.getSkus()) {
            omsOrderGoods = omsOrderVo.getSkus().stream().map(item -> {
                //构建订单项数据
                OmsOrderGoods goods = builderOrderItem(item);
                goods.setOrderSn(orderSn);

                return goods;
            }).collect(Collectors.toList());
        }

        return omsOrderGoods;

    }

    /**
     * 构建某一个订单项的数据
     * @param item
     * @return
     */
    private OmsOrderGoods builderOrderItem(OmsOrderGoods item) {

        OmsOrderGoods goods = new OmsOrderGoods();

        final Long skuId = item.getSkuId();
        final PmsSku sku = this.pmsSkuService.getById(skuId);

        // 减库存前，先验证库存是否足够扣减，如有一个商品sku库存不够，则订单创建失败
        if (item.getSkuNum() > sku.getStockNum()) {
            // 库存不足
            log.info("库存不足，skuId：{} 商品：{}, sku库存：{}, 下单数量：{}", sku.getId(), sku.getSkuName(), sku.getStockNum(), item.getSkuNum());
            throw new BizException("商品库存不足");
        }

        // 商品的spu信息
        final PmsSpu spu = this.pmsSpuService.getById(sku.getSpuId());
        final PmsBrand brand = this.pmsBrandService.getById(spu.getBrandId());
        goods.setSpuId(spu.getId());
        goods.setSpuName(spu.getName());
        goods.setSpuBrand(null != brand ? brand.getName() : null);
        goods.setCategoryId(spu.getCateId());

        // 商品的sku信息
        goods.setSkuId(skuId);
        goods.setSkuName(sku.getSkuName());
        goods.setSkuPrice(sku.getSalePrice());
        goods.setSkuNum(item.getSkuNum());
        goods.setSkuPic(sku.getSkuImg());
        goods.setSkuAttrsVals(sku.getDescar());

        // 商品的积分信息
        goods.setGiftGrowth(goods.getSkuPrice().multiply(new BigDecimal(item.getSkuNum())).intValue());
        goods.setGiftIntegration(goods.getSkuPrice().multiply(new BigDecimal(item.getSkuNum())).intValue());

        // 订单项的价格信息
        goods.setPromotionAmount(BigDecimal.ZERO);
        goods.setCouponAmount(BigDecimal.ZERO);
        goods.setIntegrationAmount(BigDecimal.ZERO);

        // 当前订单项的实际金额.总额 - 各种优惠价格

        // 原来的价格
        BigDecimal origin = goods.getSkuPrice().multiply(new BigDecimal(goods.getSkuNum().toString()));

        //原价减去优惠价得到最终的价格
        BigDecimal subtract = origin.subtract(goods.getCouponAmount())
                .subtract(goods.getPromotionAmount())
                .subtract(goods.getIntegrationAmount());


        final OmsOrderVo omsOrderVo = threadLocalOrderVo.get();

        // 会员信息
        final UmsMember member = this.umsMemberService.getById(omsOrderVo.getMemberId());
        // 会员级别
        final UmsMemberLevel level = this.umsMemberLevelService.getById(member.getLevelId());
        // 判断会员级别，是否满足打折条件
        if (level.getLevel() == 2 || level.getLevel() == 3) {
            final BigDecimal ratio = new BigDecimal(level.getRebate().toString()).divide(new BigDecimal("100"));
            BigDecimal ratioAmount = subtract.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
            // 实际支付
            goods.setRealAmount(ratioAmount);
        } else {
            // 实际支付
            goods.setRealAmount(subtract);
        }


        return goods;
    }

    /**
     * 验价(计算价格、积分等信息)
     * @param order
     * @param omsOrderGoods
     */
    private void computePrice(OmsOrder order, List<OmsOrderGoods> omsOrderGoods) {
        //总价
        BigDecimal total = new BigDecimal("0.0");
        //优惠价
        BigDecimal coupon = new BigDecimal("0.0");
        BigDecimal intergration = new BigDecimal("0.0");
        BigDecimal promotion = new BigDecimal("0.0");

        //积分、成长值
        Integer integrationTotal = 0;
        Integer growthTotal = 0;

        //订单总额，叠加每一个订单项的总额信息
        for (OmsOrderGoods goods : omsOrderGoods) {

            //优惠价格信息
            coupon = coupon.add(goods.getCouponAmount());
            promotion = promotion.add(goods.getPromotionAmount());
            intergration = intergration.add(goods.getIntegrationAmount());

            //总价
            total = total.add(goods.getRealAmount());

            //积分信息和成长值信息
            integrationTotal += goods.getGiftIntegration();
            growthTotal += goods.getGiftGrowth();

        }

        //订单价格相关的
        order.setTotalAmount(total);

        order.setCouponAmount(coupon);
        order.setIntegrationAmount(intergration);
        //设置积分成长值信息
        order.setIntegration(integrationTotal);
        order.setGrowth(growthTotal);

        // 会员信息
        final UmsMember member = this.umsMemberService.getById(order.getMemberId());
        // 会员级别
        final UmsMemberLevel level = this.umsMemberLevelService.getById(member.getLevelId());

        //// 判断会员级别，是否满足打折条件
        //if (level.getLevel() == 2 || level.getLevel() == 3 || level.getLevel() == 8) {
        //    log.info("=========================>>"+level.getLevel()+"===>"+level.getRebate());
        //    final BigDecimal ratio = new BigDecimal(level.getRebate().toString()).divide(new BigDecimal("100"));
        //    BigDecimal ratioAmount = totalAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
        //    confirmVo.setPayPrice(ratioAmount);
        //    log.info(confirmVo.getPayPrice());
        //} else {
        //    confirmVo.setPayPrice(totalAmount.setScale(2, BigDecimal.ROUND_DOWN));
        //}

        // 判断会员级别，是否满足打折条件
        log.info(level.getLevel()+"======");
        if(level.getLevel() == 2 || level.getLevel() == 3 || level.getLevel() == 8) {
            final BigDecimal ratio = new BigDecimal(level.getRebate().toString()).divide(new BigDecimal("100"));
            BigDecimal ratioAmount = total.add(order.getFreightAmount()).multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
            log.info("===="+ratioAmount);
            //设置应付总额(总额+运费)
            order.setPayAmount(ratioAmount);
        } else {
            //设置应付总额(总额+运费)
            order.setPayAmount(total.add(order.getFreightAmount()));
        }
        ////设置应付总额(总额+运费)
        //order.setPayAmount(total.add(order.getFreightAmount()));

        log.info("==>>==>>"+order.getPayAmount());

        // 优惠金额（总金额-应付金额）
        order.setPromotionAmount(order.getTotalAmount().subtract(order.getPayAmount()).setScale(2, BigDecimal.ROUND_DOWN));
    }


    /**
     * 保存订单
     * @param orderCreateTo
     */
    private void saveOrder(OrderCreateTo orderCreateTo) {
        // 获取订单信息
        final OmsOrder order = orderCreateTo.getOrder();
        // 保存订单
        super.save(order);

        // 获取订单项信息
        final List<OmsOrderGoods> orderGoods = orderCreateTo.getOrderGoods();
        //批量保存订单项数据
        this.omsOrderGoodsService.saveBatch(orderGoods);
    }


    @Override
    @Transactional
    public boolean closeOrderMQ(Long orderId) {

        OmsOrder order = super.getById(orderId);

        /**
         * 订单超时未付款，系统关单
         */
        if (null != order && order.getStatus() <= 0) { // 用户超时未付款，关单
            log.info("*******************订单超时未付款，系统关单*******************");
            log.info("订单号=[{}], 用户=[{}]", order.getOrderSn(), order.getMemberUsername());

            // 关闭微信支付
            try {
                WxPayOrderCloseResult closeResult = this.wxPayService.closeOrder(order.getOrderSn());
                if (closeResult.getReturnCode().equals("SUCCESS")) {
                    log.info("关闭微信支付订单：{}", closeResult.getResultCode());
                } else {
                    log.error("关闭微信支付订单失败：{}", closeResult.getReturnMsg());
                }
            } catch (WxPayException e) {
                log.error("关闭微信支付订单失败：{}", e.getMessage());
            }

            // 回滚库存
            QueryWrapper<OmsOrderGoods> queryWrapper = new QueryWrapper<OmsOrderGoods>();
            queryWrapper.eq("order_sn", order.getOrderSn());
            List<OmsOrderGoods> list = this.omsOrderGoodsService.list(queryWrapper);
            for (OmsOrderGoods goods : list) {
                log.info("回滚订单商品库存，商品ID=[{}]，回滚数量=[{}]，商品名=[{}]", goods.getSkuId(), goods.getSkuNum(), goods.getSkuName());

                PmsSku sku = this.pmsSkuService.getById(goods.getSkuId());
                if (null != sku) {
                    sku.setStockNum(sku.getStockNum() + goods.getSkuNum());
                    this.pmsSkuService.updateById(sku);
                } else {
                    log.info("商品不存在，商品ID=[{}]，商品名=[{}]", goods.getSkuId(), goods.getSkuName());
                }
            }

            // 关闭订单
            this.changeOrderStatus(order.getId(), 4);

            log.info(">>>>>>>>>>>>>>>>>>>微信订单支付回调处理结束<<<<<<<<<<<<<<<<<<<");
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void remarks(OmsOrderVo vo) {
        // 订单备注
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.set("remarks", vo.getRemarks());
        updateWrapper.eq("id", vo.getId());
        super.update(updateWrapper);
    }


    @Override
    public void cancelOrder(OmsOrderVo vo) {
        // 取消订单
        this.changeOrderStatus(vo.getId(), 4);

        final SysUserVo userVo = LoginUserInterceptor.loginUser.get();

        OmsOrderOperateLog history = new OmsOrderOperateLog();
        history.setOrderId(vo.getId());
        history.setOrderStatus(4);
        history.setOperateUser(userVo.getUsername());
        history.setOperateType("商家取消订单");
        history.setOperateContent("商家取消订单");
        this.omsOrderOperateLogService.save(history);

    }

    @Override
    public OmsOrderVo confirmReceivePack(OmsOrderVo vo) {
        // 商家确认收货
        final OmsOrder order = super.getById(vo.getId());
        order.setReceiveTime(LocalDateTime.now());
        order.setStatus(3);
        super.updateById(order);

        final SysUserVo userVo = LoginUserInterceptor.loginUser.get();
        OmsOrderOperateLog history = new OmsOrderOperateLog();
        history.setOrderId(vo.getId());
        history.setOrderStatus(3);
        history.setOperateUser(userVo.getUsername());
        history.setOperateType("确认收货");
        history.setOperateContent("商家确认收货");
        this.omsOrderOperateLogService.save(history);

        return null;
    }

    @Override
    public void memberConfirmReceivePack(OmsOrderVo vo) {

        // 会员确认收货
        final OmsOrder order = super.getById(vo.getId());
        order.setReceiveTime(LocalDateTime.now());
        order.setStatus(3);
        super.updateById(order);

        final UmsMember member = this.umsMemberService.getById(vo.getMemberId());
        OmsOrderOperateLog history = new OmsOrderOperateLog();
        history.setOrderId(vo.getId());
        history.setOrderStatus(3);
        history.setOperateUser(member.getNickname());
        history.setOperateType("确认收货");
        history.setOperateContent("会员确认收货");
        this.omsOrderOperateLogService.save(history);
    }

    @Transactional
    @Override
    public void expressDelivery(OmsOrderVo vo) {
        /**
         * 涉及佣金计算
         * 用户类型：1->系统用户，无需计算佣金
         * 用户类型：2->代理商，需要计算佣金
         * 会员注册后，后台管理员为该会员匹配代理商（根据地区匹配）。
         * 该会员下单后总后台和匹配的代理商均可获得会员订单信息，且可为该订单发货，
         * 若为代理商发货，代理商可获得30%或15%的佣金（若该会员有业务代理，则代理可获得15%佣金，
         * 或为第一次下单，且有会员推荐人，则代理也是获得15%佣金，若该会员无业务代理，代理商可获得30%的佣金，）
         * 若为后台发货，则代理商不可获得佣金。
         */

        final SysUserVo userVo = LoginUserInterceptor.loginUser.get();
        final OmsOrder order = super.getById(vo.getId());


        // 用户类型为：代理商，计算代理所得佣金
        if (userVo.getType() == 2) {
            // 设置发货方为：代理商发货
            order.setShipType(2);

            // 下单会员有所属的代理商，所以需要计算代理商的佣金
            if (null != order.getAgentId()) {

                // **************************验证库存及扣减******************************

                // 获取订单的商品
                final List<OmsOrderGoods> goodsList = this.omsOrderGoodsService.getGoodsByOrderSn(order.getOrderSn());
                // 获取订单商品的SkuId
                final List<Long> skuIds = goodsList.stream().map(item -> item.getSkuId()).collect(Collectors.toList());

                // 代理商发货，验证代理商的库存是否足够
                for (OmsOrderGoods goods : goodsList) {
                    final Integer agentSkuStock = this.wmsWareSkuService.getAgentSkuStock(order.getAgentId(), goods.getSkuId());

                    if (goods.getSkuNum() > agentSkuStock) {
                        // 库存不足
                        log.info("库存不足，skuId：{} 商品：{}, sku库存：{}, 下单数量：{}", goods.getSkuId(), goods.getSkuName(), agentSkuStock, goods.getSkuNum());
                        throw new BizException("商品库存不足，请补充库存。");
                    }
                    // 记录商品数量到出库（递增）
                    this.wmsWareSkuService.getStockIncrease(order.getAgentId(), goods.getSkuId(), goods.getSkuNum());
                }

                // **************************计算提成******************************

                // 获取代理商会员
                final UmsMember agentMember = this.umsMemberService.getOne(new QueryWrapper<UmsMember>().eq("agent_id", order.getAgentId()).eq("type", 5));

                // 获取下单会员
                final UmsMember member = this.umsMemberService.getById(order.getMemberId());
                // 获取下单用户的购买成功次数
                int buyCount = this.getMemberBuyCount(order.getMemberId());

                // 下单会员的上级
                final UmsMember refereeMember = this.umsMemberService.getById(order.getRefereeMemberId());
                // 单会员的上级级别
                final UmsMemberLevel refereLevel = this.umsMemberLevelService.getById(refereeMember.getLevelId());

                //if(buyCount <= 1) { // 首次购买，计算提成
                //    log.info("当前下单会员首次购买，计算提成给代理商[会员]");
                // 下单付款金额
                final BigDecimal payAmount = order.getPayAmount();
                log.info("下单付款金额：{}", payAmount);
                BigDecimal ratio = BigDecimal.ZERO;

                // 代理商的提成百分比，如果下单会员有所属业务代理，则代理商只得15%的提成，如果无所属业务代理，则代理商可的30%的提成
                // 下单会员的上级是VIP会员级别，并且下单会员是首次购买。（VIP会员和代理商各15%提成）
                // 下单会员的上级是VIP会员级别，并且下单会员不是首次购买。（代理商获得30%提成）

                if (null != order.getRefereeMemberId()) {
                    if(buyCount <= 1) {// 首次购买，下单会员的上级是VIP会员级别，并且下单会员是首次购买。（VIP,业务代理和代理商各15%提成）
                        if(refereLevel.getLevel() == 3 || refereLevel.getLevel() == 4) { // VIP,业务代理
                            //代理商获得15%提成
                            ratio = new BigDecimal(15).divide(new BigDecimal("100"));
                        }
                    } else { // 非首次购买
                        //如果上级会员的级别是业务代理，则业务代理和代理商各15%
                        if(refereLevel.getLevel() == 4) { // 业务代理
                            //代理商获得15%提成
                            ratio = new BigDecimal(15).divide(new BigDecimal("100"));
                        } else {
                            // 非首次下单，但是下单会员的上级级别不是业务代理的话，代理商获取30%提成
                            ratio = new BigDecimal(30).divide(new BigDecimal("100"));
                        }
                    }
                } else {
                    ratio = new BigDecimal(30).divide(new BigDecimal("100"));
                }


                log.info("代理商提成百分比：{}", ratio);
                BigDecimal commissionAmount = payAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
                log.info("代理商提成金额：{}", commissionAmount);

                // 记录到佣金冻结表
                FmsMemberCommisionFreeze cz = new FmsMemberCommisionFreeze();
                // 资金类型：1->推广佣金，2->分销佣金
                cz.setBankrollType(2);
                cz.setMemberId(agentMember.getId());
                cz.setMemberName(agentMember.getNickname());

                cz.setSaleGoodsOrderSn(order.getOrderSn());
                cz.setSaleGoodsOrderAmount(order.getPayAmount());

                // 状态：1->待到账，2->已到账，3->锁定（用户申请退款，防止退款时间超过14天），4->已取消(用户14天内申请退款，佣金扣除不到账)
                cz.setStatus(3);
                cz.setCommissionPercent(ratio);
                cz.setFreezeAmount(commissionAmount);
                // 是否可提现：1->可提现，2->不可提现
                cz.setIsWithdraw(2);
                cz.setRemarks("代理商提成");
                this.fmsMemberCommisionFreezeService.save(cz);

                log.info("==>分销提成完成");
                //} else {
                //    log.info("当前下单会员非首次购买，无需计算提成给代理商");
                //}

            }

        } else {
            // 设置发货方为：系统发货
            order.setShipType(1);
            log.info("订单发货，发货用户为系统用户无需计算订单提成给代理商");
        }


        // 快递信息
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.set("deliver_type", vo.getDeliverType());
        updateWrapper.set("delivery_company", vo.getDeliveryCompany());
        updateWrapper.set("delivery_sn", vo.getDeliverySn());
        updateWrapper.set("delivery_time", LocalDateTime.now());
        updateWrapper.eq("id", vo.getId());
        super.update(updateWrapper);

        // 订单发货
        order.setStatus(2);
        super.updateById(order);

        OmsOrderOperateLog history = new OmsOrderOperateLog();
        history.setOrderId(vo.getId());
        history.setOrderStatus(2);
        history.setOperateUser(userVo.getUsername());
        history.setOperateType("商家发货");
        history.setOperateContent("商家发货");
        this.omsOrderOperateLogService.save(history);

    }

    @Override
    public void orderRemarks(OmsOrderVo vo) {
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.set("remarks", vo.getRemarks());
        updateWrapper.eq("id", vo.getId());
        super.update(updateWrapper);
    }

    @Override
    public void changeOrderStatus(Long orderId, Integer status) {
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.set("status", status);
        updateWrapper.eq("id", orderId);
        super.update(updateWrapper);
    }

    @Override
    public void changeIsRefund(Long orderId, Integer isRefund) {
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.set("is_refund", isRefund);
        updateWrapper.eq("id", orderId);
        super.update(updateWrapper);
    }

}